package com.web.controller.web;

import com.github.pagehelper.Page;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.web.dao.*;
import com.web.domain.*;
import com.web.domain.dataTable.BootstrapTableColumns;
import com.web.domain.dataTable.BootstrapTableResponse;
import com.web.dto.MerchantUser;
import com.web.entity.*;
import com.web.service.LogVersionService;
import com.web.service.RoleService;
import com.web.service.SysMenuService;
import com.web.service.UserService;
import com.web.utils.WindPageHelper;
import lombok.Data;
import org.apache.commons.codec.digest.DigestUtils;
import org.apache.commons.lang3.ArrayUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.propertyeditors.StringTrimmerEditor;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.stereotype.Controller;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.ui.Model;
import org.springframework.web.bind.WebDataBinder;
import org.springframework.web.bind.annotation.*;

import javax.servlet.http.HttpServletRequest;
import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

import static org.apache.commons.lang3.StringUtils.isBlank;
import static org.apache.commons.lang3.StringUtils.isNotBlank;

/**
 * @author xukk
 * @date 2017/9/13
 */
@Controller
public class SysController {

    @Autowired
    private SysMenuMapper sysMenuMapper;
    @Autowired
    private SysMenuService sysMenuService;
    @Autowired
    private RegionRecordMapper regionRecordMapper;
    @Autowired
    private UserAccountMapper userAccountMapper;
    @Autowired
    private UserMapper userMapper;
    @Autowired
    private RoleMapper roleMapper;
    @Autowired
    private VersionMapper versionMapper;
    @Autowired
    private LogVersionMapper logVersionMapper;
    @Autowired
    private PermissionMapper permissionMapper;
    @Autowired
    private UserService userService;
    @Autowired
    private LogVersionService logVersionService;
    @Autowired
    private RoleMenuMapper roleMenuMapper;
    @Autowired
    private RolePermissionMapper rolePermissionMapper;


    @Data
    public static class UserColumns extends BootstrapTableColumns {
        private String username;
        private String phone;
        private Integer level;
        private String province;
        private String city;
        private String region;
    }

    @InitBinder
    public void initBinder(WebDataBinder binder) {
        binder.registerCustomEditor(String.class, new StringTrimmerEditor(true));
    }


    @GetMapping("sys/{path}")
    public String path(@PathVariable String path, Model model) {
        MUser user = (MUser) SecurityContextHolder.getContext()
                .getAuthentication()
                .getPrincipal();
        int isAdmin = 0;
        for (MRole r : user.getRoles()) {
            if ("1".equals(r.getRoleId())) {
                isAdmin = 1;
            }
        }
        model.addAttribute("isAdmin", isAdmin);
        return "sys/" + path;
    }

    /*******************************
     *系统菜单
     ********************************/


    @GetMapping("sys/get/menus")
    @ResponseBody
    public List getMenus() {
        SysMenuExample sysMenuExample = new SysMenuExample();
        sysMenuExample.setOrderByClause("sort asc");
        List<SysMenu> sysMenus = sysMenuMapper.selectByExample(sysMenuExample);
        return sysMenus;
    }

    @GetMapping("sys/get/tree/menus")
    @ResponseBody
    public List getTreeMenus() {
        SysMenuExample sysMenuExample = new SysMenuExample();
        sysMenuExample.setOrderByClause("sort asc");
        List<SysMenu> sysMenus = sysMenuMapper.selectByExample(sysMenuExample);
        List<ZtreeVo> ztreeVos = Lists.newArrayList();
        if (sysMenus != null) {
            sysMenus.forEach(value -> {
                System.out.println();
                ZtreeVo ztreeVo = new ZtreeVo();
                ztreeVo.setId("" + value.getId());
                ztreeVo.setName(value.getText());
                ztreeVo.setpId("" + value.getPid());
                if (value.getPermissions() != null && value.getPermissions().size() > 0) {
                    System.out.println();
                    for (Permission permission : value.getPermissions()) {
                        System.out.println();
                        ZtreeVo ztreeVo1 = new ZtreeVo();
                        ztreeVo1.setId("m" + permission.getId());
                        ztreeVo1.setpId("" + value.getId());
                        ztreeVo1.setName(permission.getText());
                        ztreeVos.add(ztreeVo1);
                    }
                }
                ztreeVos.add(ztreeVo);
            });
        }
        return ztreeVos;
    }

    /**
     * enable | unable menu
     *
     * @param menuId
     * @param enabled
     * @return
     */
    @PostMapping("sys/enable/menu")
    @ResponseBody
    public WebResponse enableMenu(@RequestParam(required = true) Long menuId, @RequestParam(required = true) Boolean enabled) {
        if (sysMenuMapper.enableById(menuId, enabled) > 0) {
            return WebResponse.updateOk();
        } else {
            return WebResponse.fail(WebResponse.UF);
        }
    }

    @GetMapping("sys/get/menu")
    @ResponseBody
    public WebResponse getMenu(SysMenu sysMenu) throws Exception {
        SysMenu sysMenu1 = sysMenuMapper.selectByPrimaryKey(sysMenu.getId());
        if (sysMenu1 == null) {
            return WebResponse.fail("对象为空");
        } else {
            if (sysMenu1.getPid() != null && sysMenu1.getPid() != 0) {
                sysMenu1.setParent(sysMenuMapper.selectByPrimaryKey(sysMenu1.getPid()));
            }
            return WebResponse.ok("", sysMenu1);
        }
    }

    @PostMapping("sys/add/menu")
    @ResponseBody
    public WebResponse addMenu(SysMenu sysMenu) throws Exception {

        return sysMenuService.addSysMenu(sysMenu);
    }

    @PostMapping("sys/del/menu")
    @ResponseBody
    public WebResponse delMenu(Long menuId) throws Exception {
        return sysMenuService.delSysMenu(menuId);

    }

    @PostMapping("sys/update/menu")
    @ResponseBody
    @Transactional
    public WebResponse updateMenu(SysMenu sysMenu) throws Exception {
        return sysMenuService.updateMenu(sysMenu);
    }


    /*******************************
     *用户管理
     ********************************/


    @GetMapping("sys/query/users")
    @ResponseBody
    public BootstrapTableResponse getUsers(UserColumns userColumns) {

        UserExample userExample = new UserExample();
        if (hasOneNotBlank(userColumns.getPhone(), userColumns.getUsername())) {
            if (isNotBlank(userColumns.getPhone())) {
                userExample.or().andPhoneLike("%" + userColumns.getPhone() + "%");
            }
            if (isNotBlank(userColumns.getUsername())) {
                userExample.or().andUsernameLike("%" + userColumns.getUsername() + "%");
            }
        }
        if (StringUtils.isNotBlank(userColumns.getSort())) {
            if (userColumns.getSort().equals("createTime")) {
                userExample.setOrderByClause("create_time" + " " + userColumns.getOrder());
            }
        }
        WindPageHelper.startPage(userColumns.getPageNumber(), userColumns.getPageSize(), "id");
        userMapper.selectRoleByExample(userExample);
        WindPageHelper.Page page = WindPageHelper.endPage();
        BootstrapTableResponse bootstrapTableResponse = new BootstrapTableResponse();
        bootstrapTableResponse.setResult(page.getResult());
        bootstrapTableResponse.setTotalCount(page.getTotal());
        return bootstrapTableResponse;
    }

    @GetMapping("sys/query/merAgent")
    @ResponseBody
    public BootstrapTableResponse merAgent(UserColumns userColumns) {
        int i = 0;
        if (userColumns.getProvince() != null) {
            i += 1;
        }
        if (userColumns.getCity() != null) {
            i += 1;
        }
        if (userColumns.getRegion() != null) {
            i += 1;
        }
        userColumns.setLevel(i);
        BootstrapTableResponse bootstrapTableResponse = new BootstrapTableResponse();
        PageHelper.startPage(userColumns.getPageNumber(), userColumns.getPageSize());
        Page<MerchantUser> page = userMapper.selectByUser(userColumns);
        bootstrapTableResponse.setResult(page.getResult());
        bootstrapTableResponse.setTotalCount(page.getTotal());
        return bootstrapTableResponse;

    }


    @RequestMapping("sys/check/user/{param}")
    @ResponseBody
    public ValidResponse checkUserParam(User user, @PathVariable String param) throws Exception {
        UserExample userExample = new UserExample();
        switch (param) {
            case "username":
                userExample.createCriteria().andUsernameEqualTo(user.getUsername());
                break;
            case "phone":
                userExample.createCriteria().andPhoneEqualTo(user.getPhone());
                break;
            default:
                break;
        }
        List<User> userList = userMapper.selectByExample(userExample);
        userList = userList.stream().filter(value -> value.getEnabled()).collect(Collectors.toList());
        if (userList != null && userList.size() > 0) {
            return ValidResponse.builder().valid(false).build();
        } else {
            return ValidResponse.builder().valid(true).build();
        }
    }

    public Boolean hasOneNotBlank(final CharSequence... css) {
        if (ArrayUtils.isEmpty(css)) {
            return false;
        }
        for (final CharSequence cs : css) {
            if (!isBlank(cs)) {
                return true;
            }
        }
        return false;
    }

    @PostMapping("sys/add/user")
    @ResponseBody
    public WebResponse addUser(User user, Long[] roleIds) throws Exception {
        RoleExample roleExample = new RoleExample();
        roleExample.createCriteria().andIdIn(Lists.newArrayList(roleIds));
        user.setRoles(roleMapper.selectByExample(roleExample));
        return userService.addUser(user);
    }

    //重置密码
    @PostMapping("sys/resetPassword/user")
    @ResponseBody
    public WebResponse resetPassword(User user) throws Exception {
        user.setPassword(DigestUtils.md5Hex(user.getPassword()));
        userMapper.updateByPrimaryKeySelective(user);
        return WebResponse.updateOk();
    }


    @PostMapping("sys/enable/user")
    @ResponseBody
    public WebResponse enableUser(@RequestParam(required = true) Long userId, @RequestParam(required = true) Boolean enabled) {
        if (userMapper.enableById(userId, enabled) > 0) {
            return WebResponse.updateOk();
        } else {
            return WebResponse.fail(WebResponse.UF);
        }
    }

    @PostMapping("sys/del/user")
    @ResponseBody
    public WebResponse delUser(Long userId) throws Exception {
        return userService.delUser(userId);
    }

    @GetMapping("sys/get/user")
    @ResponseBody
    public WebResponse getUser(User user) throws Exception {
        UserExample userExample = new UserExample();
        userExample.createCriteria().andIdEqualTo(user.getId());
        userExample.setPaging(false);
        List<User> userList = userMapper.selectRoleByExample(userExample);
        Map map = Maps.newHashMap();
        if (userList == null || userList.size() == 0) {
            return WebResponse.fail("对象为空");
        } else {
            map.put("user", userList.get(0));
            map.put("roles", getRoles());
            return WebResponse.ok("", map);
        }
    }

    @GetMapping("/sys/get/getRegion")
    @ResponseBody
    public WebResponse getRegion(RegionRecord record) throws Exception {

        Map map = Maps.newHashMap();
        RegionRecord regionRecord = regionRecordMapper.selectByUid(record.getuId());
        if (regionRecord == null) {
            map.put("status", 1);
            return WebResponse.ok("", map);
        } else {
            map.put("status", 0);
            map.put("record", regionRecord);
            return WebResponse.ok("", map);
        }
    }

    @RequestMapping(value = "/sys/merchant/add")
    @ResponseBody
    public WebResponse add(MerchantUser merchantUser) {
        Date date = new Date();
        int i = 0;
        if (merchantUser.getProvince() != null) {
            i += 1;
        }
        if (merchantUser.getCity() != null) {
            i += 1;
        }
        if (merchantUser.getRegion() != null) {
            i += 1;
        }
        try {
            RegionRecord regionRecord = regionRecordMapper.selectByUid(merchantUser.getId());
            RegionRecord setRecord = new RegionRecord();
            if (i == 1) {
                setRecord = regionRecordMapper.selectProvince(merchantUser.getProvince());
            } else if (i == 2) {
                setRecord = regionRecordMapper.selectProvinceAndCity(merchantUser.getProvince(), merchantUser.getCity());
            } else if (i == 3) {
                setRecord = regionRecordMapper.selectProvinceAndCityAndRegion(merchantUser.getProvince(), merchantUser.getCity(), merchantUser.getRegion());
            }
            if (setRecord != null) {
                return WebResponse.fail("设置的代理地区已经有代理商，请先解除原代理商代理关系，再设置新的代理关系");
            } else {
                setRecord = new RegionRecord();
                setRecord.setuId(merchantUser.getId());
                setRecord.setCreateTime(date);
                setRecord.setModifyTime(date);
                setRecord.setLevel(i);
                setRecord.setProvince(merchantUser.getProvince());
                if (merchantUser.getCity() != null) {
                    setRecord.setCity(merchantUser.getCity());
                }

                if (merchantUser.getRegion() != null) {
                    setRecord.setRegion(merchantUser.getRegion());
                }

                if (regionRecord == null) {
                    //添加
                    regionRecordMapper.insertSelective(setRecord);
                } else {
                    //清除原纪录，添加新纪录
                    regionRecordMapper.deleteByPrimaryKey(regionRecord.getId());
                    regionRecordMapper.insertSelective(setRecord);
                }
                UserAccount userAccount = userAccountMapper.selectByUid(merchantUser.getId());
                if (userAccount == null) {
                    UserAccount account = new UserAccount();
                    account.setCreateTime(date);
                    account.setModifyTime(date);
                    account.setuId(merchantUser.getId());
                    account.setProfit(new BigDecimal("0"));
                    userAccountMapper.insertSelective(account);
                }

                return WebResponse.ok("添加成功！");
            }
        } catch (Exception e) {
            e.printStackTrace();
            return WebResponse.fail(WebResponse.CF);
        }
    }

    @RequestMapping(value = "/sys/merchant/del")
    @ResponseBody
    public WebResponse del(MerchantUser merchantUser) {
        try {
            RegionRecord regionRecord = regionRecordMapper.selectByUid(merchantUser.getId());
            regionRecordMapper.deleteByPrimaryKey(regionRecord.getId());
            return WebResponse.ok("代理关系解除成功！");

        } catch (Exception e) {
            e.printStackTrace();
            return WebResponse.fail(WebResponse.CF);
        }
    }


    @PostMapping("sys/update/user")
    @ResponseBody
    public WebResponse updateUser(User user, Long[] roleIds) throws Exception {
        return userService.updateUser(user, roleIds);
    }


    /*******************************
     *版本管理
     ********************************/


    @GetMapping("sys/get/versions")
    @ResponseBody
    public List getVersions() {
        VersionExample versionExample = new VersionExample();
        return versionMapper.selectByExample(versionExample);
    }

    @GetMapping("sys/get/logVersions")
    @ResponseBody
    public List getLogVersions() {
        PageHelper.startPage(1, 10);
        LogVersionExample logVersionExample = new LogVersionExample();
        logVersionExample.setOrderByClause("modify_time desc");
        List list = logVersionMapper.selectByExample(logVersionExample);
        PageInfo<LogVersion> p = new PageInfo<LogVersion>(list);
        return p.getList();
    }


    @PostMapping("sys/update/version")
    @ResponseBody
    public WebResponse updateVersion(Version version) throws Exception {
        if (version.getId() == null || version.getId() == 0) {
            return WebResponse.fail("对象为空");
        }
        Version version1 = versionMapper.selectByPrimaryKey(version.getId());
        if (version1 == null) {
            return WebResponse.fail("对象为空");
        }
        if (version.getMinVersion() != null && !version.getMaxVersion().equals(version1.getMaxVersion())) {
            version1.setMaxVersion(version.getMaxVersion());
        }
        if (version.getMinVersion() != null && !version.getMinVersion().equals(version1.getMinVersion())) {
            version1.setMinVersion(version.getMinVersion());
        }
        if (!StringUtils.equals(version1.getDownLoadUrl(), version.getDownLoadUrl())) {
            version1.setDownLoadUrl(version.getDownLoadUrl());
        }
        version1.setModifyTime(new Date());
        if (versionMapper.updateByPrimaryKey(version1) > 0) {
            //添加到日志
            logVersionService.addLogVersion(version1);
            return WebResponse.updateOk();
        } else {
            return WebResponse.fail(WebResponse.UF);
        }

    }


    /*******************************
     *角色管理
     ********************************/

    @Autowired
    private RoleService roleService;

    @GetMapping("sys/get/roles")
    @ResponseBody
    public List getRoles() {
        return roleMapper.selectByExample(new RoleExample());
    }

    @GetMapping("sys/get/menu_permission")
    @ResponseBody
    public List getMenuPermission() {
        List<SysMenu> sysMenus = sysMenuMapper.selectPermissonByExample();
        List<ZtreeVo> ztreeVos = Lists.newArrayList();
        if (sysMenus != null) {
            sysMenus.forEach(value -> {
                ZtreeVo ztreeVo = new ZtreeVo();
                ztreeVo.setId("" + value.getId());
                ztreeVo.setName(value.getText());
                ztreeVo.setpId("" + value.getPid());
                if (value.getPermissions() != null && value.getPermissions().size() > 0) {
                    for (Permission permission : value.getPermissions()) {
                        ZtreeVo ztreeVo1 = new ZtreeVo();
                        ztreeVo1.setId("m" + permission.getId());
                        ztreeVo1.setpId("" + value.getId());
                        ztreeVo1.setName(permission.getText());
                        ztreeVos.add(ztreeVo1);
                    }
                }
                ztreeVos.add(ztreeVo);
            });
        }
        return ztreeVos;
    }


    @GetMapping("sys/get/menu_permission/selected")
    @ResponseBody
    public List getMenuPermissionSelected(@RequestParam(required = true) Long roleId) {
        List<ZtreeVo> ztreeVos = getMenuPermission();
        List<ZtreeVo> ztreeVos1 = Lists.newArrayList();
        RoleMenuExample roleMenuExample = new RoleMenuExample();
        roleMenuExample.createCriteria().andRoleIdEqualTo(roleId);
        List<RoleMenuKey> roleMenuKeys = roleMenuMapper.selectByExample(roleMenuExample);
        RolePermissionExample rolePermissionExample = new RolePermissionExample();
        rolePermissionExample.createCriteria().andRoleIdEqualTo(roleId);
        List<RolePermissionKey> rolePermissionKeys = rolePermissionMapper.selectByExample(rolePermissionExample);
        if (roleMenuKeys != null) {
            for (int i = ztreeVos.size() - 1; i >= 0; i--) {
                ZtreeVo ztreeVo = ztreeVos.get(i);
                if (ztreeVo.getId().startsWith("m")) {
                    if (rolePermissionKeys != null) {
                        for (RolePermissionKey rolePermissionKey : rolePermissionKeys) {
                            if (("m" + rolePermissionKey.getPermissionId()).equals(ztreeVo.getId())) {
                                ztreeVos1.add(ztreeVo);
                            }
                        }

                    }

                } else {
                    if (roleMenuKeys != null) {
                        for (RoleMenuKey roleMenuKey : roleMenuKeys) {
                            if (("" + roleMenuKey.getMenuId()).equals(ztreeVo.getId())) {
                                ztreeVos1.add(ztreeVo);
                            }
                        }
                    }
                }
            }
        }
        return ztreeVos1;
    }

    @PostMapping("sys/enable/role")
    @ResponseBody
    public WebResponse enableRole(@RequestParam(required = true) Long roleId, @RequestParam(required = true) Boolean enabled) {
        if (roleMapper.enableById(roleId, enabled) > 0) {
            return WebResponse.updateOk();
        } else {
            return WebResponse.fail(WebResponse.UF);
        }
    }

    @PostMapping("sys/add/role")
    @ResponseBody
    public WebResponse addRole(Role role, String[] permissionIds) {
        //return WebResponse.fail("123");
        return roleService.addRole(role, permissionIds);
    }

    @PostMapping("sys/del/role")
    @ResponseBody
    public WebResponse delRole(Long roleId) {
        if (roleMapper.deleteByPrimaryKey(roleId) > 0) {
            return WebResponse.ok("");
        } else {
            return WebResponse.fail(WebResponse.UF);
        }
    }

    @PostMapping("sys/update/role")
    @ResponseBody
    public WebResponse udpateRole(Role role, String[] permissionIds) {
        return roleService.updateRole(role, permissionIds);
    }

    /*******************************
     *权限管理
     ********************************/


    @GetMapping("sys/get/permission")
    @ResponseBody
    public List getPermission(@RequestParam(required = true) Long menuId) {
        PermissionExample permissionExample = new PermissionExample();
        permissionExample.createCriteria().andMenuIdEqualTo(menuId);
        return permissionMapper.selectByExample(permissionExample);
    }

    @RequestMapping(value = "sys/merchantAgent",
            method = RequestMethod.GET)
    public String merchantAgent(Model model, HttpServletRequest request) {
        return "merchantAgent";
    }

}
